package com.gt.util.db;

import com.gt.util.model.SqlTemplateParseResult;
import com.gt.util.prop.PropUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.StringTemplateResourceLoader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author WUREN
 * @desc SQL模板工具类
 * @create 2019-01-30 23:52
 **/
public class SqlTemplateUtil {
    private static Logger logger = Logger.getLogger(SqlTemplateUtil.class);
    private static final String dirName = "sql";
    /**
     * 保存sql模板到内存
     */
    public static Map<String, String> sqlMapper = new HashMap<String, String>();

    /**
     * 模板解析器
     */
    private static GroupTemplate gtInstance;

    static {
        // 字符串模板加载器
        StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
        Configuration cfg = null;
        try {
            cfg = Configuration.defaultConfiguration();
            gtInstance = new GroupTemplate(resourceLoader, cfg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据SQL模板文件名、SQL标签名获取对应SQL语句
     * @param templateName  classpath:sql/*.sql，其中*的部分
     * @param sqlTagName    模板文件中###begin("*")其中*的部分
     * @return
     */
    public static String getSql(String templateName, String sqlTagName) {
        String sql = null;
        InputStream is = null;
        List<String> list = new ArrayList<String>();

        try {
            sql = sqlMapper.get(templateName+"|"+sqlTagName);
            if(null != sql){
                // 从内存读取SQL模板
                return sql;
            }

            is = SqlTemplateUtil.class.getClassLoader().getResourceAsStream(dirName+"/"+templateName+".sql");

            InputStreamReader read = new InputStreamReader(is, "utf-8");// 考虑到编码格式
            BufferedReader bufferedReader = new BufferedReader(read);
            String lineTxt = null;

            while ((lineTxt = bufferedReader.readLine()) != null)
            {
                list.add(lineTxt);
            }
            bufferedReader.close();
            read.close();

            String content = StringUtils.join(list," ").trim();
            Pattern pattern = Pattern.compile("#begin\\(\\\""+sqlTagName+"\\\"\\)(.*?)#end");
            Matcher matcher = pattern.matcher(content);
            if(matcher.find()){
                sql = matcher.group(1).trim();
                sqlMapper.put(templateName+"|"+sqlTagName, sql);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if(null!=is){
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sql;
    }

    /**
     * SQL模板解析，适用于使用 #param(name) 方式占位变量的SQL模板
     * 使用Beetl模板引擎字符串解析
     * @param templateName  classpath:sql/*.sql，其中*的部分
     * @param sqlTagName    模板文件中###begin("*")其中*的部分
     * @param params        变量Map
     * @return              完整SQL语句
     */
    public static String parseSql(String templateName, String sqlTagName, Map<String, Object> params) {
        SqlTemplateParseResult parseResult = new SqlTemplateParseResult();
        String sql = null;
        try{
            sql = getSql(templateName, sqlTagName);
            if(null == sql){
                logger.error("没有找到对应的SQL模板");
                return null;
            }

            // 模板解析器
            Template t = gtInstance.getTemplate(sql);

            if(null != params){
                Set<String> set = params.keySet();
                Iterator iter = set.iterator();
                while(iter.hasNext()){
                    String key = (String)iter.next();
                    t.binding(key, params.get(key));
                }
            }
            sql = t.render();
        } catch(Exception e) {
            logger.error("解析SQL模板失败 【"+templateName+"."+sqlTagName+"】");
            e.printStackTrace();
            return null;
        }
//        System.out.println("Beetl解析结果："+sql);
        return sql;
    }
}
